﻿using DataType;
using DataType.Actions;
using DataType.CustomEnumType;
using DataType.JudgeResults;
using DataType.MessageType;
using MapCalclator;
using OprsSimulator.Operators;
using OprsSimulator.OprAttributes;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ActionsJudge
{
    internal static class GuideShootJudge
    {
        public static List<IJudgeResult> ToJudge(IBasicAction acts, List<OperatorMsg> oprs, Map map, ShootJudgeTable shootJudgeTable)
        {
            List<IJudgeResult> judgeResults = new List<IJudgeResult>();
            //取得并判断数据
            GuideShootAction action = (GuideShootAction)acts;
            // 算子存在的标志位
            bool opr_save = false;
            bool guided_opr_save = false;
            bool enemy_save = false;
            OperatorMsg opr = oprs[0];
            OperatorMsg guided_opr = oprs[0];
            OperatorMsg enemy = oprs[0];
            // 寻找动作涉及到的各个算子
            foreach (OperatorMsg oper in oprs)
            {
                if (opr_save && guided_opr_save && enemy_save) break;

                if (oper.obj_id == action.ObjID)
                {
                    opr = oper;
                    opr_save = true;
                }
                if (oper.obj_id == action.TargetObjID)
                {
                    enemy = oper;
                    enemy_save = true;
                }
                if (oper.obj_id == action.GuidedObjID)
                {
                    guided_opr = oper;
                    guided_opr_save = true;
                }
            }
            if (!opr_save)
            {
                Trace.TraceWarning($"无效裁决：态势中没有ID为{action.ObjID}的算子");// 输出警告日志
                return new List<IJudgeResult>();
            }
            if (!guided_opr_save)
            {
                Trace.TraceWarning($"无效裁决：被引导的算子不存在");
                return new List<IJudgeResult>();
            }
            if (!enemy_save)
            {
                Trace.TraceWarning($"无效裁决：引导射击的攻击对象不存在");
                return new List<IJudgeResult>();
            }
            if (action.Type != ActionType.GuideShoot)
            {
                Trace.TraceWarning("无效裁决：算子的动作类型有误，应该是引导射击类型");
                return new List<IJudgeResult>();
            }

            if (!opr.guide_ability)
            {
                Trace.TraceWarning("无效裁决：算子无引导射击能力，不可引导射击");
                return new List<IJudgeResult>();
            }
            if (enemy.type != (int)OprType.Vehicle)
            {
                Trace.TraceWarning($"无效裁决：引导重型导弹只能攻击车辆");
                return new List<IJudgeResult>();
            }

            // 需要先判定使用的是什么类型弹药，根据武器类型获取弹药名称
            int bulletType = (int)shootJudgeTable.GetWeapon(action.WeaponID).Bullet;
            if (guided_opr.remain_bullet_nums[bulletType] <= 0)
            {
                Trace.TraceWarning($"无效裁决：没有可用弹药");
                return new List<IJudgeResult>();
            }
            if (guided_opr.color == enemy.color)
            {
                Trace.TraceWarning($"无效裁决：射击算子与目标算子是同一方");
                return new List<IJudgeResult>();
            }
            // 步兵、无人战车、无人机都要考虑
            if (opr.weapon_cool_time > 0)
            {
                Trace.TraceWarning($"无效裁决：引导算子正处于冷却中");
                return new List<IJudgeResult>();
            }
            // 如果是步兵和无人战车，除了冷却，还要考虑当前状态是否可以引导射击
            if (opr.sub_type == (int)OprSubType.Infantry || opr.sub_type == (int)OprSubType.UGV)
            {
                if (opr.weapon_unfold_time > 0)
                {
                    Trace.TraceWarning($"无效裁决：引导算子的武器正在展开或折叠");
                    return new List<IJudgeResult>();
                }
                if (opr.weapon_unfold_state == 0)
                {
                    Trace.TraceWarning($"无效裁决：引导算子的武器处于锁定状态");
                    return new List<IJudgeResult>();
                }
                if (opr.change_state_remain_time > 0)
                {
                    Trace.TraceWarning($"无效裁决：引导算子正在转换状态");
                    return new List<IJudgeResult>();
                }
                if (opr.get_on_remain_time > 0 || opr.get_off_remain_time > 0)
                {
                    Trace.TraceWarning($"无效裁决：引导算子正在上车或者下车,不能引导射击");
                    return new List<IJudgeResult>();
                }
                if (opr.keep)
                {
                    Trace.TraceWarning($"无效裁决：引导算子被压制");
                    return new List<IJudgeResult>();
                }
                if (opr.launcher == -1)
                {
                    Trace.TraceWarning($"无效裁决：引导算子没有所属车辆");
                    return new List<IJudgeResult>();
                }
            }
            if (guided_opr.weapon_cool_time > 0)
            {
                Trace.TraceWarning($"无效裁决：被引导算子的武器处于冷却中");
                return new List<IJudgeResult>();
            }
            if (guided_opr.weapon_unfold_time > 0)
            {
                Trace.TraceWarning($"无效裁决：被引导算子的武器正在展开或折叠");
                return new List<IJudgeResult>();
            }
            if (guided_opr.weapon_unfold_state == 0)
            {
                Trace.TraceWarning($"无效裁决：被引导算子的武器处于锁定状态");
                return new List<IJudgeResult>();
            }
            if (guided_opr.move_state == (int)MoveStateType.March)
            {
                Trace.TraceWarning($"无效裁决：被引导算子处于行军状态");
                return new List<IJudgeResult>();
            }
            if (guided_opr.target_state == (int)MoveStateType.March && guided_opr.change_state_remain_time > 0)
            {
                Trace.TraceWarning($"无效裁决：被引导射击算子处于行军状态转换过程中");
                return new List<IJudgeResult>();
            }
            if (!guided_opr.A1 && guided_opr.target_state == (int)MoveStateType.Shelt && guided_opr.change_state_remain_time > 0)
            {
                Trace.TraceWarning($"无效裁决：无行进间射击能力的算子处于掩蔽状态转换过程中，不能被引导射击");
                return new List<IJudgeResult>();
            }
            if (!guided_opr.A1 && !guided_opr.stop)
            {
                Trace.TraceWarning($"无效裁决：无行进间射击能力的算子不处于静止状态，不能被引导射击");
                return new List<IJudgeResult>();
            }
            else if (guided_opr.A1 && !guided_opr.stop)
            {
                if (action.WeaponID != WeaponType.MediumDirectGun && action.WeaponID != WeaponType.LargeDirectGun)
                {
                    Trace.TraceWarning($"无效裁决：使用的不是坦克主炮（大号、中号直瞄炮），不可行进间射击");
                    return new List<IJudgeResult>();
                }
            }
            if (!guided_opr.carry_weapon_ids.Contains((int)action.WeaponID))
            {
                Trace.TraceWarning($"无效裁决：被引导射击算子未装配该行动的武器");
                return new List<IJudgeResult>();
            }
            if (guided_opr.get_on_remain_time > 0 || guided_opr.get_off_remain_time > 0)
            {
                Trace.TraceWarning($"无效裁决：算子正在上车或者下车,不能射击");
                return new List<IJudgeResult>();
            }
            // 引导算子can_see为true（可以看见敌方），被引导算子attack_level > 0（攻击等级大于0）
            bool can_see = map.CanSeeTerrain(opr.type, enemy.type, opr.cur_hex, enemy.cur_hex, enemy.sub_type, opr.observe_distance, enemy.move_state);
            int distance = map.GetDistance(guided_opr.cur_hex, enemy.cur_hex);
            int attack_level = shootJudgeTable.CalcAttackLevel(can_see, guided_opr.remain_bullet_nums, action.WeaponID, enemy.type, distance, guided_opr.blood);
            if (attack_level < 0)
            {
                Trace.TraceWarning($"无效裁决：无效射击");
                return new List<IJudgeResult>();
            }
            if (enemy.blood <= 0)
            {
                Trace.TraceWarning($"无效裁决：射击目标{action.TargetObjID}血量为零");
                return new List<IJudgeResult>();
            }

            //计算裁决结果
            // 计算高度差修正
            int elev_rect;
            // elev_diff为射击方与被射击方之间的高度差
            int elev_diff = -(map[guided_opr.cur_hex / 100, guided_opr.cur_hex % 100].elev -
                map[enemy.cur_hex / 100, enemy.cur_hex % 100].elev) / map.ElevGrade;
            if (elev_diff > 8) elev_diff = 8;// 如果高差大于8则按8计算
            if (elev_diff <= 0 | distance > 12) elev_rect = 0;//如果是 高打低 或者 距离远  则不做高差修正
            else
            {
                elev_rect = shootJudgeTable.GetElevRect(elev_diff, distance);// 否则就调用shootJudgeTable中的高差修正表，对攻击等级修正（elev_rect为小于等于0的整数）
            }
            if (attack_level >= -elev_rect) attack_level += elev_rect;// 如果攻击等级被修正后大于0则正常修正
            else attack_level = 0;// 如果小于0就修正为0

            // 第一个随机数random1用于获取初始战斗结果ori_damage,  random2在进行战损结果修正之后得到random2_rect， random2_rect取得战损结果修正值rect_damage， 对ori_damage修正后得到最终战损damage
            int random1, random2, random2_rect, rect_damage, ori_damage, damage;
            // 攻击等级小于等于0，不造成伤害  变量附上初始值用于直接形成裁决结果
            if (attack_level <= 0)
            {
                random1 = -1;
                random2 = -1;
                random2_rect = -1;
                ori_damage = 0;
                rect_damage = 0;
                damage = -1;
            }
            else
            {
                // 对车辆目标
                if (enemy.type == (int)OprType.Vehicle)
                {
                    // 计算origin_damage
                    Random random = new Random();
                    int r11 = random.Next(1, 7);
                    int r12 = random.Next(1, 7);
                    random1 = r11 + r12;            // 2到12 随机数
                    if (random1 < 2) random1 = 2;
                    if (random1 > 12) random1 = 12;

                    // 裁决结果是否为纯压制的标志位
                    bool flag_keep = false;
                    if (action.WeaponID == WeaponType.InfantryLightWeapon)// 步兵轻武器
                    {
                        //（直瞄武器对人员/）步兵轻武器对车辆战斗结果表
                        ori_damage = shootJudgeTable.GetToInfantryOriDamageTab(random1, attack_level);// 取得初始战损
                    }
                    else
                    {
                        // 直瞄武器对车辆
                        int ori_damage_row = shootJudgeTable.GetOriDamageTabRow(guided_opr.blood, attack_level);
                        ori_damage = shootJudgeTable.GetOriDamage(ori_damage_row, random1);// 取得初始战损
                    }
                    // damage为-1表示裁决结果damage为0且压制
                    if (ori_damage == -1)
                    {
                        flag_keep = true;// 压制标志位为true
                        ori_damage = 0;// 战损置为零（没有伤害的纯压制）
                    }

                    // 计算随机数2修正值random2_rect
                    int val = 0;// 记录random2将会被修正多少
                    // 射击算子被压制、正在机动
                    if (guided_opr.keep) val -= 1;
                    if (guided_opr.speed > 0) val -= 1;
                    if (guided_opr.sub_type == (int)OprSubType.Tank &&  // 如果坦克算子在水上地形
                        map[guided_opr.cur_hex / 100, guided_opr.cur_hex % 100].cond == TerrainType.River)
                    {
                        val -= 1;
                    }
                    // 射击目标在城镇、丛林、河流
                    if (map[enemy.cur_hex / 100, enemy.cur_hex % 100].cond == TerrainType.City) val -= 1;
                    if (map[enemy.cur_hex / 100, enemy.cur_hex % 100].cond == TerrainType.Forest) val -= 2;
                    if (map[enemy.cur_hex / 100, enemy.cur_hex % 100].cond == TerrainType.River) val -= 2;
                    // 敌方正在掩蔽、机动、堆叠、行军
                    if (enemy.move_state == (int)MoveStateType.Shelt) val -= 2;
                    if (enemy.speed > 0) val -= 2;
                    if (enemy.stack) val += 2;
                    if (enemy.move_state == (int)MoveStateType.March) val += 4;

                    // 生成2-12的随机数
                    int r21 = random.Next(1, 7);
                    int r22 = random.Next(1, 7);
                    random2 = r21 + r22;
                    // 用val对随机数2进行修正
                    random2_rect = random2 + val;

                    // 计算最终战损damage
                    int random2_rect_ind;// 将random2_rect限定在-3到12之间，赋值给random2_rect_ind用于查表
                    if (random2_rect <= -3) random2_rect_ind = -3;
                    else if (random2_rect >= 12) random2_rect_ind = 12;
                    else random2_rect_ind = random2_rect;

                    // 查表取得战损修正值
                    rect_damage = shootJudgeTable.GetDamageRect((ArmorType)enemy.armor, random2_rect_ind);

                    // 对初始战损修正，形成最终战损
                    damage = ori_damage + rect_damage;
                    // 如果最终战损damage为0且无压制，为无效射击
                    if (damage == 0)
                    {
                        if (!flag_keep)
                        {
                            damage = -1;
                        }
                    }   
                }
                // 重型导弹不可以打步兵，无效射击
                else
                {
                    random1 = -1;
                    random2 = -1;
                    random2_rect = -1;
                    ori_damage = 0;
                    rect_damage = 0;
                    damage = -1;
                }
            }

            bool flag_shoot = true;
            // 最终战损小于0为无效射击
            if (damage < 0) flag_shoot = false;

            // 根据上面得到的结果修改judge_info信息
            GuideShootJudgeResult guideShootJudgeResult = new GuideShootJudgeResult(
                action.ObjID, flag_shoot, (BulletType)bulletType, attack_level, guided_opr.blood, guided_opr.obj_id, (Color)guided_opr.color, (OprSubType)guided_opr.sub_type, damage, distance, elev_diff, ori_damage, random1, random2, random2_rect, rect_damage, (Color)enemy.color, enemy.obj_id, (OprSubType)enemy.sub_type, action.WeaponID
                );

            judgeResults.Add(guideShootJudgeResult);

            return judgeResults;
        }
    }
}
